package com.simplemobiletools.camera.filter

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ContentValues
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.BitmapFactory.*
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
import android.os.*
import android.provider.MediaStore
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.app.module.camera.ext.runOnUIThread
import com.atom.module.document.helper.BitmapHelper
import com.atom.module.image.filter.*
import com.atom.module.logger.Logger
import com.simplemobiletools.camera.R
import com.simplemobiletools.camera.document.RenderThread
import com.simplemobiletools.camera.utils.Adapter
import com.simplemobiletools.camera.utils.FileUtil
import org.wysaid.common.SharedContext
import org.wysaid.nativePort.CGEImageHandler
import java.io.IOException
import java.lang.Exception
import java.lang.ref.ReferenceQueue
import java.lang.ref.SoftReference
import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.FutureTask

/**
 * All rights Reserved, Designed By www.rongdasoft.com
 * @version V1.0
 * @Title: ModuleFIlterActivity
 * @Description:
 * @author: wuyongzheng
 * @date: 2022/3/18
 * @Copyright: 2022/3/18 www.rongdasoft.com Inc. All rights reserved.
 */
class AndroidGpuImagePlusActivity : AppCompatActivity() {

    private var imgFilterSource: ImageView? = null
    private var imgFilterRenderer: ImageView? = null
    private var renderer: RenderThread? = null
    private var uiHandle = Handler(Looper.getMainLooper())
    private val evictionQueue: Queue<Bitmap> = ConcurrentLinkedQueue()

    @SuppressLint("MissingSuperCall")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_gpu_image_filter)
        imgFilterSource = findViewById(R.id.imgFilterSource)
        imgFilterRenderer = findViewById(R.id.imgFilterRenderer)
        findViewById<View>(R.id.pickImage).setOnClickListener {
            pickImage()
        }
        findViewById<View>(R.id.photoImage).setOnClickListener {
            takePhoto()
        }
        findViewById<View>(R.id.resetDefault).setOnClickListener {
            setBitmap(
                decodeResource(
                    this.resources,
                    R.mipmap.module_filter
                )
            )
        }

        renderer = RenderThread("GPUImageRenderer")
        setBitmap(
            decodeResource(
                this.resources,
                R.mipmap.module_filter
            )
        )
    }

    override fun onDestroy() {
        renderer?.recycle()
        renderer = null
        super.onDestroy()
    }

    private var imageUri: Uri? = null
    private fun takePhoto() {
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        if (takePictureIntent.resolveActivity(this.packageManager) != null) {
            val values = ContentValues()
            values.put(MediaStore.Images.Media.TITLE, "New Picture")
            values.put(MediaStore.Images.Media.DESCRIPTION, "From Camera")
            this.imageUri =
                this.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, this.imageUri)
            this.startActivityForResult(
                takePictureIntent,
                1024
            )
        }
    }

    private fun pickImage() {
        val intent = Intent(Intent.ACTION_PICK, null)
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
        startActivityForResult(
            intent,
            2048
        )
    }

    private fun handleFile(bitmap: Bitmap, degree: Int) {
        val spBitmap = rotaingImageView(degree, bitmap)
        val matrix = Matrix()
        matrix.setScale(0.5f, 0.5f)
        setBitmap(
            Bitmap.createBitmap(
                spBitmap!!, 0, 0, spBitmap.width,
                spBitmap.height, matrix, true
            )
        )
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 1024 && resultCode == RESULT_OK) {
            try {
                if (imageUri != null) {
                    val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
                    val realPathFromURI: String? = FileUtil.getFilePathByUri(this, imageUri)
                    handleFile(bitmap, readPictureDegree(realPathFromURI))
                }
            } catch (e: IOException) {
                Logger.e(e)
            }
        }
        if (requestCode == 2048 && resultCode == RESULT_OK) {
            data ?: return
            imageUri = data.data
            try {
                if (imageUri != null) {
                    val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
                    val realPathFromURI: String? = FileUtil.getFilePathByUri(this, imageUri)
                    handleFile(bitmap, readPictureDegree(realPathFromURI))
                }
            } catch (e: IOException) {
                Logger.e(e)
            }
        }
    }

    fun recycler(bitmap: Bitmap?) {
        bitmap?.also {
            if (it.isRecycled) {
                return
            }
            it.recycle()
        }
    }

    var recycleSize: Int = 0
    fun setBitmap(bitmap: Bitmap) {
        recycleSize++
        if (recycleSize == 10) {
            releaseEvictedResources()
            recycleSize = 0
        }
        // recycler(resBitmap)
        // recycler(rendererBitmap)
        evictionQueue.offer(bitmap)
        imgFilterSource?.setImageBitmap(
            bitmap
        )
        val futureTask = RendererTask(object : Callable<Bitmap> {
            override fun call(): Bitmap {
                val renderer =
                    "@adjust sharpen 3.88 3.2 @curve RGB(0, 0)(100, 173)(255, 255) @adjust contrast 1.16 @beautify bilateral 100 20 1 @adjust contrast 1.04 @adjust exposure 0.06 @adjust blur 0.99 3.5 "
                val handler = CGEImageHandler()
                handler.initWithBitmap(bitmap)
                handler.setFilterWithConfig(renderer)
                handler.processFilters()
                val resultBitmap = handler.resultBitmap;
                handler.release()
                return resultBitmap
            }
        }) {
            evictionQueue.offer(it)
            runOnUIThread {
                imgFilterRenderer?.setImageBitmap(
                    it
                )
            }
        }
        renderer?.postRunnable(futureTask)
    }

    fun releaseEvictedResources() {
        var evicted: Bitmap?
        while (evictionQueue.poll().also { evicted = it } != null) {
            try {
                recycler(evicted)
            } catch (ignored: Exception) {

            }
        }
    }

    class RendererTask(callable: Callable<Bitmap>, private val block: (Bitmap?) -> Unit) :
        FutureTask<Bitmap>(callable) {

        override fun run() {
            super.run()
            block.invoke(get())
        }
    }

    fun rotaingImageView(angle: Int, bitmap: Bitmap): Bitmap? {
        val matrix = Matrix()
        matrix.postRotate(angle.toFloat())
        return Bitmap.createBitmap(
            bitmap, 0, 0,
            bitmap.width, bitmap.height, matrix, true
        )
    }

    fun readPictureDegree(path: String?): Int {
        var degree = 0
        try {
            val exifInterface = ExifInterface(path!!)
            val orientation = exifInterface.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL
            )
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
                ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
                ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
            }
        } catch (e: IOException) {
            Log.e(
                "DocumentActivity",
                e.message!!
            )
        }
        return degree
    }
}
